<template>
<vs-modal :show.sync="show" effect="fade" width="800px">
  <div class="modal-header" slot="modal-header">
    <h4 class="modal-title">{{$t('common.detail')}}</h4>
  </div>  
  <div class="modal-body" slot="modal-body">
    <my-file-upload 
      :upload-file="uploadFile" 
      :min-size="minSize"   
      :max-size="maxSize" 
      :check-file-name="checkFileName"  
      :accept="accept" 
      upload-type="upgrade" 
      :upload-file-name="uploadFileName" 
      :error="onError"></my-file-upload>   
  </div>
  <div class="modal-footer" slot="modal-footer">
  </div>    
</vs-modal>   
</template>

<script>
import _ from 'lodash'
import async from 'async'
import ebus from 'libs/ebus.js'
import toast from 'libs/toast.js'
import {http} from 'share/common/api.js'

export default {
  props: {
    accept: {
      type: String,
      default: ''
    },
    checkFileName: {
      type: Function
    },
    uploadFileName: {
      type: String
    },
    concurrency: {
      type: Number,
      default: 5
    }
  },
  data () {
    return {
      show: false,
      minSize: 1*1024*1024,
      maxSize: 256*1024*1024, 
    }
  },
  methods: {
    onError (reason) {
      if (reason) {
        toast.e(this, this.$t('common.fail'), reason)
      } else {
        toast.e(this, this.$t('common.fail'), this.$t('error.unknown'))
      }
    },
    stepLogin (host, task, cb) {
      var dev = task.dev
      dev.stage = 'logining'
      http(host, '/api/auth/login', 'POST', {
        username: 'api',
        password: 'api'
      }).then(function(res) {
        if (res && res.data && res.data.code === 0) {
          cb(null, host, task)
        } else {
          cb({msg: `code[${res.data.code}]`})
        }
      }, function(res) {
        cb({msg: 'error'})
      })
    },
    stepUploadFile (host, task, cb) {
      var dev = task.dev
      var params = task.params
      var upload = {
        onprogress: function(e) {
          dev.progress = Math.floor(100 * e.loaded/e.total)
        },
        onabort: function(e) {
          dev.status = 'abort'
        },
        ontimeout: function(e) {
          dev.status = 'timeout'
        },    
      }      
      dev.stage = 'uploading'
      let uri = `/api/storage/file?type=${params.uploadType}&path=${params.fileName}`
      http(host, uri, 'PUT', params.content, {
        timeout: 180 * 1000, //180s=3min
        headers: {
          'Content-Type': 'application/octet-stream'
        },
        upload: upload
      }).then(function(res) {
        if (res && res.data && res.data.code === 0) {
          cb(null, host, task)
        } else {
          cb({msg: `code[${res.data.code}]`})
        }
      }, function(res) {
        cb({msg: 'error'})
      }) 
    },
    stepStartUpdate(host, task, cb) {
      var dev = task.dev
      let updateCmd = this.cfg.module.updateCmd
      dev.stage = 'start'
      http(host, updateCmd.uri, 'POST', updateCmd.body)
      .then(function(res) {
        if (res && res.data && res.data.code === 0) {
          cb(null, host, task)
        } else {
          cb({msg: `code[${res.data.code}]`})
        }
      }, function(res) {
        cb({msg: 'error'})
      })
    },
    stepUpdateState(host, task, cb) {
      let stepUpdateState = this.cfg.module.stepUpdateState
      if (stepUpdateState) {
        stepUpdateState(host, task, cb)
      } else {
        var dev = task.dev
        dev.stage = 'end'
        cb(null)
      }
    },
    devUpgrade (task, callback) {
      let dev = task.dev
      let module = this.cfg.module
      let host = `http://${dev.ipaddr}:${module.port}`

      async.waterfall([
        function(cb) {
          cb(null, host, task)      
        }, 
        this.stepLogin,
        this.stepUploadFile,
        this.stepStartUpdate,
        this.stepUpdateState,
        ], 
        function (err, result) {
          callback(err)
        }
      )
    },
    uploadFile (params) {
      var devs = this.cfg.devs
      var queue = async.queue(this.devUpgrade, this.concurrency)
      _.forEach(devs, (item) => {
        item.stage = 'waiting'
        queue.push({
          dev: item,
          params: params
        }, function(err) {
          if (err) {
            item.result = err.msg
          } else {
            item.result = 'success'
          }
        })
      })
      queue.drain = function() {
        params.endCb()
      }.bind(this)
      this.show = false
    },
    onShow (val) {
      this.cfg = val
      this.show = true
    }
  },
  ready () {
    ebus.on('show-upload-file-detail', this.onShow)
  }
}
</script>

<style>
</style>